﻿using System;
using CSharpConsoleTestSolution.Bean;

namespace CSharpConsoleTestSolution.Demo {
    public class P11_Operator2 {
        /**
         * 隐式构造器 : 时间15:30
         */
        public static void hidden_constructor_exam() {
            var student = new { Name = "张三", age = 23 };
            Console.WriteLine(student.Name);
            Console.WriteLine(student.GetType().Name);  //<>f__AnonymousType0`2
        }
        
        /**
         * 子类隐藏父类方法(new, 编程中不常见) : 时间22:50
         */
        public static void hidden_parent_method_exam() {
            var person = new Person("张三");
            var student = new Student("学生李四");
            person.PrintHello();
            student.PrintHello();
            Person.PrintHelloStatic();
            Student.PrintHelloStatic();
        }
        
        private class Student: Person {
            public Student(string name) : base(name) {
            }

            //new修饰符(在这儿不叫操作符), 隐藏父类方法, 经测试new可以省略
            public new void PrintHello() {
                Console.WriteLine("Hello Student!");
            }

            //new修饰符(在这儿不叫操作符), 隐藏父类方法, 经测试new可以省略
            public new static void PrintHelloStatic() {
                Console.WriteLine("Hello Student Static!");
            }
        }

    
    
        /**
         * 打印二进制 & 溢出检查( checked(x) ): 时间28:00
         */
        public static void print_binary_checked_exam() {
            /*const*/ uint x = uint.MaxValue;               //最大值
            Console.WriteLine($"x = uint.MaxValue = {x}");  //x = 4294967295

            var binStr = Convert.ToString(x, 2);     //进制转换, 转换成二进制
            Console.WriteLine($"x.binary = {binStr}");      //binary = 11111111111111111111111111111111

            /*const*/ uint y = unchecked(x + 1);            //默认是 unchecked()
            Console.WriteLine($"unchecked(x + 1) = {y}");   //y = 0

            try {
                /*const*/ uint z = checked(x + 1);          //System.OverflowException: 算术运算导致溢出。
                Console.WriteLine($"checked(x + 1) = {z}");
            }
            catch (OverflowException e) {
                Console.WriteLine(e);
                // throw;
            }

            unchecked {                                       //unchecked 语句块
                /*const*/ uint a = x + 1;               
                Console.WriteLine($"unchecked(语句块) {{x + 1;}} = {a}");  //checked(语句块) {x + 1;} = 0
            }
        }


        /**
         * delegate(操作符[一般不用于操作符,已被lambda替代] & 声明委托的数据类型): 时间30:50
         */
        public static void delegate_exam() {
            //见MainWindow: this.btn.Click += delegate(object sender, RoutedEventArgs args) {}
        }


        /**
         * sizeof, 获取对象在内存中所占尺寸: 时间00:36:43
         */
        public static void sizeof_exam() {
            Console.WriteLine($"sizeof(int) = {sizeof(int)}");          //4
            Console.WriteLine($"sizeof(long) = {sizeof(long)}");        //8
            Console.WriteLine($"sizeof(ulong) = {sizeof(ulong)}");      //8
            Console.WriteLine($"sizeof(double) = {sizeof(double)}");    //8
            Console.WriteLine($"sizeof(decimal) = {sizeof(decimal)}");  //16 decimal(小数；十进制) 常用于金融计算
            //结构体, sizeof获取自定义结构体尺寸是, 报错, 要放在 unsalf 上下文里面
            unsafe {
                Console.WriteLine($"sizeof(Struct_Student) = {sizeof(Struct_Student)}");    //16
            }
        }


        /**
         * -> 指针: 时间00:41:55
         *          1. 指针操作∵要操作内存, ∴只能放在 unsafe 上下文里面
         *          2. C# 中严格规定: 指针操作, 取地址操作, 用指针访问成员的操作, 只能操作 结构体struct 类型, 不能操作引用类型
         */
        public static void pointer_exam() {
            unsafe {
                Struct_Student stu;
                stu.Id = 1;
                stu.Score = 9;

                Struct_Student* pStu = &stu;    //&stu 取地址, 交给1个指针变量
                pStu->Score = 100;              //通过指针 间接访问
                Console.WriteLine(stu.ToString());
            }
        }


        /**
         * -> 一元操作符( +, -, !, ~, ++x, --x, (T)x, await, &x, *x ): 时间00:45:10
         */
        public static void _1yuan_exam() {
            unsafe {
                Struct_Student stu;
                stu.Id = 1;
                stu.Score = 9;

                Struct_Student* pStu = &stu;    //&stu: 取地址符号, 交给1个指针变量
                pStu->Score = 100;              //通过指针 间接访问
                Console.WriteLine(stu.ToString());

                (*pStu).Score = 999;            //*pStu: 取引用符号, 拿到指针所指的对象
                Console.WriteLine(stu.ToString());
            }


            int x = +int.MinValue;  //-2147483648
            int y = -x;             //-2147483648
            //            Convert.ToString: 转换为2进制Str,  PadLeft: 转换为32位, 不足前方补0
            string xStr = Convert.ToString(x, 2).PadLeft(32, '0');  //10000000000000000000000000000000
            Console.WriteLine($"x = {x}, y = {y}, xStr = {xStr}");


            int a = 12345678;       // 12345678
            int b = ~a;             //-12345679,    ~ 二进制按位取反
            int c = ~a + 1;         //-12345678,    按位取反 + 1 = 求相反数
            Console.WriteLine($"a = {a}, b = {b}");

            //转换成2进制                                   int 是 32位, 不足前方补 '0'
            string aStr = Convert.ToString(a, 2).PadLeft(32, '0');  //00000000101111000110000101001110
            string bStr = Convert.ToString(b, 2).PadLeft(32, '0');  //11111111010000111001111010110001
            string cStr = Convert.ToString(c, 2).PadLeft(32, '0');  //11111111010000111001111010110010
            Console.WriteLine($"aStr = {aStr}, bStr = {bStr}, cStr = {cStr}");


            bool b1 = true;
            bool b2 = !b1;
            Console.WriteLine($"b1 = {b1}, b2 = {b2}");


            //++x, x++, --x, x--
        }
    }
}